package com.ap.core.jbehave.confirmpayment;

import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;

import com.ap.core.cxf.jaxb.managepayment.ConfirmPayment1Request;
import com.ap.core.cxf.jaxb.managepayment.ConfirmPayment1Response;
import com.ap.core.cxf.jaxb.managepayment.RetrieveRTP1Request;
import com.ap.core.cxf.jaxb.managepayment.RetrieveRTP1Response;
import com.ap.core.cxf.jaxb.managertp.SubmitRTP1Request;
import com.ap.core.cxf.jaxb.managertp.SubmitRTP1Response;
import com.ap.core.cxf.jaxb.managertp.SubmitRTPMessageType;
import com.ap.core.cxf.jaxb.msghdr.MessageType;
import com.ap.core.cxf.jaxb.rtp.TransactionCheckOutType;
import com.ap.core.jbehave.BaseTransitionRTPSteps;
import com.ap.core.jbehave.StoryContext;
import com.ap.core.util.JaxbUtil;
import com.ap.core.util.Nullable;
import com.ap.core.util.TypedKey;
import com.core.ap.wsdl.managepaymentservice_1.ConfirmPayment1Fault;
import com.core.ap.wsdl.managepaymentservice_1.ManagePayment1PortType;
import com.core.ap.wsdl.managepaymentservice_1.RetrieveRTP1Fault;
import com.core.ap.wsdl.managertpservice_1.ManageRTP1PortType;
import com.core.ap.wsdl.managertpservice_1.SubmitRTP1Fault;

public class ConfirmPaymentSteps extends BaseTransitionRTPSteps {

	protected static final TypedKey<Nullable<SubmitRTP1Response>> SUBMIT_RTP_RESPONSE  = new TypedKey<>("SubmitRTPResponseType");
    protected static final TypedKey<Nullable<RetrieveRTP1Response>> RETRIEVE_RTP_RESPONSE  = new TypedKey<>("RetreiveRTPResponseType");
    protected static final TypedKey<Nullable<ConfirmPayment1Response>> CONFIRM_PAYMENT_RESPONSE  = new TypedKey<>("ConfirmPaymentResponseType");
	
	protected SubmitRTP1Request submitRTPRequest;
    protected RetrieveRTP1Request retrieveRTPRequest;
    protected ConfirmPayment1Request confirmPayment1Request;
	
	public ConfirmPaymentSteps(StoryContext storyContext) {
        super(storyContext);
	}

	@Given("the OSB has submitted a structurally valid SUBMITRTPFORMOB request to APCore")
	public void giveBankCompletedMComPayment() throws Exception {
        processRequiredMessagesForConfirmPaymentMessage(SubmitRTPMessageType.SUBMITRTPFORMOB);
	}


    @When("APCore receives the structurally valid CONFIRMPAYMENT request from OSB")
	public void whenAPReceivesPaymentConfirmation() throws Exception {
        processConfirmPaymentMessage();

	}


    @Then("the RSPTOPAYMENTCONFIRMATION message is sent to the OSB")
	public void thenAPSendsPaymentNotification() {
        doConfirmPaymentResponseAssertions(storyContext.get(CONFIRM_PAYMENT_RESPONSE), confirmPayment1Request, submitRTPRequest);
	}


    @Given("Service Consumer has submitted a valid CONFIRMPAYMENT request to APCore")
    public void giveServiceConsumerSubmittedValidRequest() throws Exception {
        processRequiredMessagesForConfirmPaymentMessage(SubmitRTPMessageType.SUBMITRTPFORBRN);
    }

    @Given("the BANKID in the request will be validated against the BANKID reference data")
    public void giveServiceConsumerSubmittedValidRequestValidBank() throws Exception {
    }

    @Given("the request has the valid APTransactionID")
    public void giveServiceConsumerSubmittedValidRequestValidApTransId() throws Exception {
    }

    @Given("the TransactionStatusCode is SUCCE")
    public void givenTransactionStatusCodeIsSUCCE(){
    }

    @When("APCore process the structurally valid CONFIRMPAYMENT request")
    public void whenAPReceivesValidPaymentConfirmation() throws Exception {
        processConfirmPaymentMessage();
    }

    @Then("the State of the existing record held on AP Core should be updated to RTP_COMPLETED")
    public void thenAPSendsPaymentNotificationRTP_COMPLETED() {
        doConfirmPaymentResponseAssertions(storyContext.get(CONFIRM_PAYMENT_RESPONSE), confirmPayment1Request, submitRTPRequest);
    }

    @Then("the OrgReqMsgId in the RSPTOPAYMENTCONFIRMATION message should be from the request")
    public void thenAPSendsOrgReqMsgIdInRSPTOPAYMENTCONFIRMATION() {
    }

    @Then("the DistributorId, MerchantIdentification, RtpId in the RSPTOPAYMENTCONFIRMATION should be populated from the SUBMITRTP request")
    public void thenAPSendsInformationinResponse() {
    }

    @Then("the RSPTOPAYMENTCONFIRMATION message is sent to the Service Consumer")
    public void thenAPSendsRSPTOPAYMENTCONFIRMATION() {
    }


    private void processRequiredMessagesForConfirmPaymentMessage(SubmitRTPMessageType messageType) throws SubmitRTP1Fault, RetrieveRTP1Fault {
        final ManageRTP1PortType singnedPort = factory.getBean(ManageRTP1PortType.class);
        submitRTPRequest = createSubmitRTPRequest(messageType);
        submitRTPRequest.getRTPSenderInfo().getDistributorInfo().setDistributorId("000001");
        submitRTPRequest.getRTPSenderInfo().getDetailMerchantInfo().getMerchantInfo().setMerchantId("000001");

        LOG.info("Given -  the OSB has submitted a structurally valid SUBMITRTPFORMOB request to APCore");
        JaxbUtil.newInstance().javaToXML(SubmitRTP1Request.class, submitRTPRequest);

        SubmitRTP1Response responseRTPType = singnedPort.submitRTP1(submitRTPRequest);

        LOG.info("AND - APCore successfully responded and stored the request with RTPSUBMITTED");
        JaxbUtil.newInstance().javaToXML(SubmitRTP1Response.class, responseRTPType);

        storyContext.put(SUBMIT_RTP_RESPONSE, Nullable.nullable(responseRTPType));

        final ManagePayment1PortType managePaymentSignedPort = factory.getBean(ManagePayment1PortType.class);
        retrieveRTPRequest = createRetrieveRTPRequest();
        
        if(SubmitRTPMessageType.SUBMITRTPFORMOB.equals(messageType)){
        	retrieveRTPRequest.getRequestInfo().setApTransactionId(responseRTPType.getResponseInfo().getApTransactionId());
        	retrieveRTPRequest.getRequestInfo().setApTRId(responseRTPType.getResponseInfo().getApTRId());
        	retrieveRTPRequest.getRequestInfo().setBRN(null);
        }else{
        	retrieveRTPRequest.getRequestInfo().setApTransactionId(null);
        	retrieveRTPRequest.getRequestInfo().setApTRId(null);
        	retrieveRTPRequest.getRequestInfo().setBRN(responseRTPType.getResponseInfo().getBRN());
        }
      
        
        retrieveRTPRequest.getRequestInfo().setFIId("000001");
        retrieveRTPRequest.getRequestInfo().setFIConsumerId("ntwdcon1");

        LOG.info("AND - OSB successfully submitted a structurally valid RetrieveRTP request to APCore");

        JaxbUtil.newInstance().javaToXML(RetrieveRTP1Request.class, retrieveRTPRequest);
        RetrieveRTP1Response retrieveRTPResponse = managePaymentSignedPort.retrieveRTP1(retrieveRTPRequest);

        LOG.info("AND - APCore successfully responded and stored the request with RTPRETRIEVED");
        JaxbUtil.newInstance().javaToXML(RetrieveRTP1Response.class, retrieveRTPResponse);

        storyContext.put(RETRIEVE_RTP_RESPONSE, Nullable.nullable(retrieveRTPResponse));
    }

    private void processConfirmPaymentMessage() throws ConfirmPayment1Fault {
        final ManagePayment1PortType managePayment1PortType = factory.getBean(ManagePayment1PortType.class);


        Nullable<RetrieveRTP1Response> retrieveRTPResponse = storyContext.get(RETRIEVE_RTP_RESPONSE);

        confirmPayment1Request = createConfirmPayment1Request(MessageType.CONFIRMPAYMENT, TransactionCheckOutType.NRMLCHK, submitRTPRequest.getDelivery().getDeliveryType());

        confirmPayment1Request.getPaymtDetails().setApTransactionId(retrieveRTPResponse.value().getRTPIdentifier().getApTransactionId());
        confirmPayment1Request.getPaymtDetails().setApTRId(retrieveRTPResponse.value().getRTPIdentifier().getApTRId());

        confirmPayment1Request.getConsumerAcct().setFIId(retrieveRTPResponse.value().getConsumerInfo().getFIId());
        confirmPayment1Request.getPaymtDetails().getPaymentStatusInfo().setTotalPaymentReqAmount(retrieveRTPResponse.value().getRTPSummary().getPaymtAmtInfo().getTotalPaymentReqAmount());
        
        JaxbUtil.newInstance().javaToXML(ConfirmPayment1Request.class, confirmPayment1Request);
        LOG.info("When -  APCore receives the structurally valid CONFIRMPAYMENT request from OSB");
        ConfirmPayment1Response confirmPayment1Response = managePayment1PortType.confirmPayment1(confirmPayment1Request);

        JaxbUtil.newInstance().javaToXML(ConfirmPayment1Response.class, confirmPayment1Response);

        storyContext.put(CONFIRM_PAYMENT_RESPONSE, Nullable.nullable(confirmPayment1Response));
    }
}
